#include "Lights.hpp"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>


void Lights::init(){

    for(int c=0;c<M;c++){
        problem[c] = 0;
        solution[c] = 0;
        matrix[c][M] = 1;
        
        int ri = (int) c/N;
        int ci = c%N;
        for(int r=0;r<M;r++){
            matrix[r][c] = 0;
        }

        matrix[c][c] = 1;
        if(ci<N-1) matrix[c+1][c] = 1;
        if(ci>0 )  matrix[c-1][c] = 1;
        if(ri>0)   matrix[c-N][c] = 1;
        if(ri<N-1) matrix[c+N][c] = 1;
    }
};


void Lights::set_problem(int *_problem){
    
    for(int i=0;i<M;i++){
        problem[i] = _problem[i];
        matrix[i][M] = (matrix[i][M] + problem[i])%2;
    }
};

void  Lights::dump() const {
    int j,k;

    for(j=0;j<M;j++)   {
        for(k=0;k<M+1;k++)   {
            std::cout<<matrix[j][k]<<' ';
        }
        std::cout << solution[j]<<std::endl;
    }
    std::cout<<std::endl;
}


int Lights::solve() {
    int   i,j,k,maxrow;
    int   tmp;

    for(i=0;i<M;i++)   {
        /*   Find   the   row   with   the   largest   first   value   */
        maxrow   =   i;
        for(int r=i+1; r<M; r++)   {
            if(abs(matrix[r][i]) > abs(matrix[maxrow][i]))
                maxrow   =   r;
        }

        /*   Swap   the   maxrow   and   ith   row   */
        for(int c=i; c<M+1; c++)   {
            tmp   =   matrix[i][c];
            matrix[i][c]   =   matrix[maxrow][c];
            matrix[maxrow][c]   =   tmp;
        }

        /*   Singular   matrix?   */
        if(abs(matrix[i][i]) < 0.00001){
            break;
            // XXX: return(FALSE);
        }

        // DEBUG: WriteSolution((int **)a,n,x);
        /*   Eliminate   the   ith   element   of   the   jth   row   */
        for(int r=i+1; r<M; r++)   {
           for(int c=M; c>=i; c--)   {
               //XXX: a[r][c] = a[r][c]  - a[i][c]   *   a[r][i]   /   a[i][i];
               matrix[r][c] = (matrix[r][c] + matrix[i][c]*matrix[r][i]/matrix[i][i])%2;
           }
        }
    }

    /*   Do   the   back   substitution   */
    srand( time(NULL) );
    for(int r=M-1; r>=0; r--)   {
        tmp   =   0;
        for(int c=r+1; c<M; c++)
           tmp   +=   matrix[r][c]   *   solution[c];
        //XXX: x[r]   =   (a[r][n]   -   tmp)   /   a[r][r];
        if(matrix[r][r] == 0)
            solution[r] = rand() & 0x01;
        else
	        solution[r]   =   (matrix[r][M]   +   tmp)%2;
    }

    return 1;
}



